<?php

/**
 * Osztálykezelő
 *
 * A rendszer valamely állapotához tartozó osztályokat kezeli.
 * Osztályokat hozzáadni a legegyszerűbben úgy lehet, hogy az osztály nevét
 * felfűzzük az osztálykezelőhöz:
 * <code>
 *     $classManager[] = 'x10_TestClass';
 * </code>
 * Az osztálykezelő a felfűzést felülbírálja: az osztályt annak neve alapján
 * tárolja asszociatívan, azonosítja annak névterét, megállapítja az elérési
 * útját, majd az ez alapján létrehozott osztály-szolgáltatót párosítja az
 * elemhez:
 * <code>
 *     $cm = x10::dedicate('x10_StateManager_ClassManager');
 *     $classPath = $cm['x10_TestClass']->classPath;
 * </code>
 *
 * @author prometheus
 */
class x10_StateManager_ClassManager extends x10_Manager
{
	public $xName = 'Osztálykezelő';

	protected $queue = array();

	/**
	 * Konstruktor.
	 * @param x10_Config $config
	 * @throws x10_E_Observer_ObservedObjectIsNotObject
	 * @throws x10_E_Observer_ObservedObjectUndefined
	 */
	public function __construct(x10_Config $config=NULL)
	{
		parent::__construct($config);
		$this->registerProvider(new x10_Provider_Descriptor('x10_StateManager_ClassProvider'));
	}

	/**
	 * Az osztály neve alapján létrehozza a megfelelő osztály-szolgáltatót,
	 * vagy amennyiben ez nem lehetséges, NULL-lal tér vissza.
	 * @param String $className
	 * @return x10_StateManager_ClassProvider
	 */
	public function createProvider($className)
	{
		$nsMan = x10::dedicate('x10_NamespaceManager');
		$ns = $nsMan->findByClassName($className);
		$result = NULL;
		if (!is_null($ns))
		{
			$result = new x10_StateManager_ClassProvider(
				new x10_Config(
					array(
						'className'	=> $className,
						'classPath'	=> $ns->get()->locate($className),
						'storable'	=> $ns->isStorable()
					)
				)
			);
		}
		return $result;
	}

	/**
	 * Felfűzi az osztálynév alapján létrehozott osztály-szolgáltatót egy
	 * átmeneti sorba (queue) és visszatér a szolgáltatóval, vagy NULL-lal, ha
	 * az osztály nem a rendszerhez tartozik.
	 * @param String $className
	 * @return x10_StateManager_ClassProvider
	 */
	public function appendQueue($className)
	{
		$prov = $this->createProvider($className);
		if (!is_null($prov))
		{
			if ($prov->isStorable()) $this->queue[$className] = $prov;
			return $prov;
		}
		else
		{
			return NULL;
		}
	}

	public function mapQueueReverse()
	{
		$revQueue = array_reverse($this->queue, TRUE);
		foreach ($revQueue as $k=>$v)
		{
			$this[$k] = $v;
		}
		unset($revQueue, $this->queue);
		$this->queue = array();
	}

	public function append($value)
	{
		$nsMan = x10::dedicate('x10_NamespaceManager');
		$ns = $nsMan->findByClassName($value);
		if (!is_null($ns))
		{
			$prov = new x10_StateManager_ClassProvider(
				new x10_Config(
					array(
						'className'	=> $value,
						'classPath'	=> $ns->get()->locate($value)
					)
				)
			);
			$this[$value] = $prov;
		}
	}

	public function offsetSet($index, $newval)
	{
		if (is_null($index) and is_string($newval))
		{
			$nsMan = x10::dedicate('x10_NamespaceManager');
			$ns = $nsMan->findByClassName($newval);
			if (!is_null($ns))
			{
				$prov = new x10_StateManager_ClassProvider(
					new x10_Config(
						array(
							'className'	=> $newval,
							'classPath'	=> $ns->get()->locate($newval)
						)
					)
				);
				$index = $newval;
				$newval = $prov;
			}
		}
		parent::offsetSet($index, $newval);
	}
}

?>